const fs = require('fs/promises')
const readline = require('readline/promises').createInterface({
  input: process.stdin,
  output: process.stdout
})

const snippet_infos = [{
  name: "nsb-make-code-snippet",
  scope: 'javascript,javascriptreact,typescript,typescriptreact',
  prefix: 'nsb-make-code-snippet',
  body: [
    "/*code_snippet* CODE_SNIPPET_BEGIN *code_snippet*/",
    "/*code_snippet* name : ${1:PREFIX} *code_snippet*/",
    "/*code_snippet* prefix : #${1:PREFIX} *code_snippet*/",
    "/*code_snippet* description : ${2:DESCRIPTION} *code_snippet*/",
    "",
    "/*code_snippet* CODE_SNIPPET_END *code_snippet*/",
  ]
}];
async function main() {
  const output_path = process.argv[process.argv.indexOf('-o') + 1]
  if (!output_path) {
    return console.error('output path not set, -o [PATH]')
  }

  const template_path = process.argv[process.argv.indexOf('-i') + 1]
  if (!template_path) {
    return console.error('template path not set, -i [PATH]')
  }
  const template_stat = await fs.stat(template_path).catch(() => void 0)
  if (!template_stat) {
    return console.error('template path not exist: ', template_stat)
  } else if (template_stat.isDirectory()) {
    for (const sub_name of await fs.readdir(template_path)) {
      const sub_path = template_path + '/' + sub_name;
      const sub_path_stat = await fs.stat(sub_path).catch(() => void 0)
      if (sub_path_stat.isFile()) {
        await read_template_file(sub_path);
      }
    }
  } else if (template_stat.isFile()) {
    await read_template_file(template_stat);
  } else {
    return console.error('template path must point to a file or dir.')
  }


  // 检查重复的名字与前缀
  const name_set = new Set();
  const prefix_set = new Set();
  for (const { name, prefix } of snippet_infos) {
    if (name_set.has(name)) {
      console.error('duplicated name found! name:', JSON.stringify(name))
      return;
    }
    if (prefix_set.has(prefix)) {
      console.error('duplicated name found! name:', JSON.stringify(name))
      return;
    }
    name_set.add(name)
    name_set.add(prefix)
  }

  const code_snippets_file_path = output_path
  const code_snippets_obj = await fs.readFile(code_snippets_file_path)
    .then(r => require('json5').parse(r.toString()))
    .catch(e => ({}))

  for (const info of snippet_infos) {
    code_snippets_obj[info.name] = { ...info }
    delete code_snippets_obj[info.name].name
    console.log('code-snippet', JSON.stringify(info.name), 'added,',
      '\n\tprefix:', JSON.stringify(info.prefix),
      '\n\tdescription:', JSON.stringify(info.description),
    )
  }
  // 
  // import ApiList from "../../api/ApiV1ProjectGetSimpleIdNameVOList_get"; // TAV
  await fs.writeFile(code_snippets_file_path, JSON.stringify(code_snippets_obj, null, 2))
}

async function read_template_file(src_file_path) {
  const src_file = await fs.readFile(src_file_path);
  let scope = '';
  if (src_file_path.endsWith('.tsx')) {
    scope = 'typescriptreact';
  } else if (src_file_path.endsWith('.ts')) {
    scope = 'typescript,typescriptreact';
  } else if (src_file_path.endsWith('.jsx')) {
    scope = 'javascript, javascriptreact';
  } else if (src_file_path.endsWith('.js')) {
    scope = 'javascript';
  }
  const lines = src_file.toString().split('\n');

  let snippet_info;

  for (let idx = 0; idx < lines.length; idx++) {
    const line = lines[idx];
    const what = line.match(/\/\*code_snippet\* (.*?) \*code_snippet\*\//)?.[1];
    if (what) {
      if (what === 'CODE_SNIPPET_BEGIN') {
        snippet_info = {
          name: '',
          scope: scope,
          prefix: '',
          description: '',
          body: []
        };
        continue;
      }
      if (what === 'CODE_SNIPPET_END') {
        if (!snippet_info) {
          console.error('/*code_snippet* CODE_SNIPPET_BEGIN *code_snippet*/ not found!');
        } else if (!snippet_info.name) {
          console.error('/*code_snippet* name : [SNIPPET_INFO_NAME]*/ not found!');
        } else if (!snippet_info.prefix) {
          console.error('/*code_snippet* prefix : [SNIPPET_INFO_PREFIX]*/ not found!');
        } else if (!snippet_info.body.length) {
          console.error('code snippet body is empty ');
        } else {
          snippet_infos.push(snippet_info);
        }
        snippet_info = void 0;
        continue;
      }
      const _kv = what.match(/(.*) : (.*)/);
      if (_kv) {
        if (!snippet_info) {
          continue;
        }
        const [_, k, v] = _kv;
        const known_keys = ['name', 'prefix', 'description'];
        if (known_keys.indexOf(k) <= -1) {
          console.error(`unkown key: ${known_key}`);
          continue;
        } else if (!v) {
          console.error(`${known_key} can be is empty`);
          continue;
        }
        snippet_info[k] = v;
        continue;
      }
    }
    if (!snippet_info) continue;
    snippet_info.body.push(line.replace(/\$\$_PLACEHOLDER_(\d)_?(.*?)?_\$\$/g, (_, a, b) => b ? `\${${a}:${b}}` : `\${${a}}`).trimEnd());
  }
}


main().finally(() => readline.close());